package org.admin.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.query.MPJLambdaQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import core.data.DataHandle;
import org.admin.entity.domain.App;
import org.admin.entity.domain.Perms;
import org.admin.entity.domain.PermsGroup;
import org.admin.entity.dto.PermsDto;
import org.admin.entity.vo.PermsFetchVo;
import org.admin.entity.vo.PermsQueryVo;
import org.admin.mapper.AppMapper;
import org.admin.mapper.PermsGroupMapper;
import org.admin.mapper.PermsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class PermsService {
    @Autowired
    private PermsMapper mapper;
    public void query(DataHandle<PermsDto, IPage<PermsQueryVo>> handle){
        PermsDto params = handle.getParams();
        // "appId", "route", "method", "power", "groupId", "*current", "size"
        // LambdaQueryWrapper<Perms> query = new LambdaQueryWrapper<>();
        MPJLambdaWrapper<Perms> query = new MPJLambdaWrapper<>();
        query.selectAll(Perms.class)
                .selectAs(App::getName, PermsQueryVo::getAppName)
                .selectAs(PermsGroup::getName, PermsQueryVo::getGroupName)
                .leftJoin(App.class, App::getId, Perms::getAppId)
                .leftJoin(PermsGroup.class, PermsGroup::getId, Perms::getGroupId)
                .orderByDesc(Perms::getCreatedAt)
                .groupBy(Perms::getId);
        // 条件查询
        if(params.getAppId() != null){
            query.eq(Perms::getAppId, params.getAppId());
        }
        if(params.getGroupId() != null){
            query.eq(Perms::getGroupId, params.getGroupId());
        }

        if(params.getMethod() != null){
            query.eq(Perms::getMethod, params.getMethod());
        }

        if(params.getRoute() != null){
            query.eq(Perms::getRoute, params.getRoute());
        }
        if(params.getName() != null){
            query.like(Perms::getName, "%" + params.getName() + "%");
        }

        if (params.getPower() != null) {
            int power = params.getPower();
            if(power == 0) {
                query.eq(Perms::getPower, 0);
            }else {
                query.or(wrapper -> {
                    int nPower = power;
                    if (nPower >= 4) {
                        query.eq(Perms::getPower, 4);
                        nPower = nPower - 4;
                    }
                    if (nPower >= 2) {
                        query.eq(Perms::getPower, 2);
                        nPower = nPower - 2;
                    }
                    if (nPower == 1) {
                        query.eq(Perms::getPower, 1);
                    }
                });
            }
        }
        IPage<PermsQueryVo> permsPage = mapper.selectJoinPage(
                new Page<>(params.getCurrent(), params.getSize()),
                PermsQueryVo.class,
                query);

        handle.success(permsPage);
    }

    public void create(DataHandle<PermsDto, ?> handle) {
        PermsDto params = handle.getParams();
        Date now = new Date();
        Perms entity = null;
        boolean doUpdate = false;
        QueryWrapper<Perms> query = new QueryWrapper<>();
        if(params.getId() == null){
            entity = new Perms();
            entity.setCreatedAt(now);
        }else{
            entity = mapper.selectById(params.getId());
            if(entity == null){
                handle.failure("id", "权限ID不存在或已删除");
                return;
            }
            query.ne("id", params.getId());
            doUpdate = true;
        }
        query.eq("route", params.getRoute());

        if(mapper.selectCount(query) > 0) {
            handle.failure("route", "与其他路由冲突");
            return;
        }

        // appId;
        if(JoinWrappers.lambda(App.class)
                .eq(App::getId, params.getAppId())
                .count() == 0){
            handle.failure("appId", "选择了不存在的应用");
            return;
        }
        // groupId;
        if(MPJWrappers.lambdaJoin(PermsGroup.class)
                .eq(PermsGroup::getId, params.getGroupId())
                .count() == 0){
            handle.failure("groupId", "选择了不存在的组");
            return;
        }

        entity.setAppId(params.getAppId());
        entity.setName(params.getName());
        entity.setRoute(params.getRoute());
        entity.setMethod(params.getMethod());
        entity.setPower(params.getPower());
        entity.setDetail(params.getDetail());
        entity.setGroupId(params.getGroupId());
        entity.setUpdatedAt(now);

        if(doUpdate){
            mapper.updateById(entity);
        }else{
            mapper.insert(entity);
        }
        handle.success();
    }

    public void info(DataHandle<PermsDto, Object> handle) {
        fetch(handle);
    }

    private void fetch(DataHandle<PermsDto, Object> handle) {
        PermsDto params = handle.getParams();
        Perms entity = mapper.selectById(params.getId());
        if(entity == null){
            handle.failure("id", "权限ID无效或已删除");
            return;
        }
        handle.success(new PermsFetchVo(entity));
    }

    public void remove(DataHandle<PermsDto, Object> handle) {
        PermsDto params = handle.getParams();
        List<Integer> ids = params.getIds();
        if(ids.isEmpty()){
            handle.failure("ids", "未提供删除项");
            return ;
        }

        if(JoinWrappers.lambda(Perms.class)
                .in(Perms::getId, ids)
                .count() != ids.size()){
            handle.failure("ids", "指定了不存在的接口");
            return;
        }

        mapper.deleteBatchIds(ids);
        handle.success();
    }
}
